<html><body>
<pre class="prettyprint">
        // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

        #ifndef UNITY_STANDARD_BRDF_INCLUDED
        #define UNITY_STANDARD_BRDF_INCLUDED
        
        #include "UnityCG.cginc"
        #include "UnityStandardConfig.cginc"
        #include "UnityLightingCommon.cginc"
        
        //-----------------------------------------------------------------------------
        // Helper to convert smoothness to roughness
        //-----------------------------------------------------------------------------
        
        float <a name="PerceptualRoughnessToRoughness">PerceptualRoughnessToRoughness</a>(float perceptualRoughness)
        {
            return perceptualRoughness * perceptualRoughness;
        }
        
        half <a name="RoughnessToPerceptualRoughness">RoughnessToPerceptualRoughness</a>(half roughness)
        {
            return sqrt(roughness);
        }
        
        // Smoothness is the user facing name
        // it should be perceptualSmoothness but we don't want the user to have to deal with this name
        half <a name="SmoothnessToRoughness">SmoothnessToRoughness</a>(half smoothness)
        {
            return (1 - smoothness) * (1 - smoothness);
        }
        
        float <a name="SmoothnessToPerceptualRoughness">SmoothnessToPerceptualRoughness</a>(float smoothness)
        {
            return (1 - smoothness);
        }
        
        //-------------------------------------------------------------------------------------
        
        inline half <a name="Pow4">Pow4</a> (half x)
        {
            return x*x*x*x;
        }
        
        inline float2 Pow4 (float2 x)
        {
            return x*x*x*x;
        }
        
        inline half3 Pow4 (half3 x)
        {
            return x*x*x*x;
        }
        
        inline half4 Pow4 (half4 x)
        {
            return x*x*x*x;
        }
        
        // Pow5 uses the same amount of instructions as generic pow(), but has 2 advantages:
        // 1) better instruction pipelining
        // 2) no need to worry about NaNs
        inline half <a name="Pow5">Pow5</a> (half x)
        {
            return x*x * x*x * x;
        }
        
        inline half2 Pow5 (half2 x)
        {
            return x*x * x*x * x;
        }
        
        inline half3 Pow5 (half3 x)
        {
            return x*x * x*x * x;
        }
        
        inline half4 Pow5 (half4 x)
        {
            return x*x * x*x * x;
        }
        
        inline half3 <a name="FresnelTerm">FresnelTerm</a> (half3 F0, half cosA)
        {
            half t = Pow5 (1 - cosA);   // ala Schlick interpoliation
            return F0 + (1-F0) * t;
        }
        inline half3 <a name="FresnelLerp">FresnelLerp</a> (half3 F0, half3 F90, half cosA)
        {
            half t = Pow5 (1 - cosA);   // ala Schlick interpoliation
            return lerp (F0, F90, t);
        }
        // approximage Schlick with ^4 instead of ^5
        inline half3 <a name="FresnelLerpFast">FresnelLerpFast</a> (half3 F0, half3 F90, half cosA)
        {
            half t = Pow4 (1 - cosA);
            return lerp (F0, F90, t);
        }
        
        // Note: Disney diffuse must be multiply by diffuseAlbedo / PI. This is done outside of this function.
        half <a name="DisneyDiffuse">DisneyDiffuse</a>(half NdotV, half NdotL, half LdotH, half perceptualRoughness)
        {
            half fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
            // Two schlick fresnel term
            half lightScatter   = (1 + (fd90 - 1) * Pow5(1 - NdotL));
            half viewScatter    = (1 + (fd90 - 1) * Pow5(1 - NdotV));
        
            return lightScatter * viewScatter;
        }
        
        // NOTE: Visibility term here is the full form from Torrance-Sparrow model, it includes Geometric term: V = G / (N.L * N.V)
        // This way it is easier to swap Geometric terms and more room for optimizations (except maybe in case of CookTorrance geom term)
        
        // Generic Smith-Schlick visibility term
        inline half <a name="SmithVisibilityTerm">SmithVisibilityTerm</a> (half NdotL, half NdotV, half k)
        {
            half gL = NdotL * (1-k) + k;
            half gV = NdotV * (1-k) + k;
            return 1.0 / (gL * gV + 1e-5f); // This function is not intended to be running on Mobile,
                                            // therefore epsilon is smaller than can be represented by half
        }
        
        // Smith-Schlick derived for Beckmann
        inline half <a name="SmithBeckmannVisibilityTerm">SmithBeckmannVisibilityTerm</a> (half NdotL, half NdotV, half roughness)
        {
            half c = 0.797884560802865h; // c = sqrt(2 / Pi)
            half k = roughness * c;
            return SmithVisibilityTerm (NdotL, NdotV, k) * 0.25f; // * 0.25 is the 1/4 of the visibility term
        }
        
        // Ref: http://jcgt.org/published/0003/02/03/paper.pdf
        inline float <a name ="SmithJointGGXVisibilityTerm">SmithJointGGXVisibilityTerm</a> (float NdotL, float NdotV, float roughness)
        {
        #if 0
            // Original formulation:
            //  lambda_v    = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
            //  lambda_l    = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
            //  G           = 1 / (1 + lambda_v + lambda_l);
        
            // Reorder code to be more optimal
            half a          = roughness;
            half a2         = a * a;
        
            half lambdaV    = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2);
            half lambdaL    = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
        
            // Simplify visibility term: (2.0f * NdotL * NdotV) /  ((4.0f * NdotL * NdotV) * (lambda_v + lambda_l + 1e-5f));
            return 0.5f / (lambdaV + lambdaL + 1e-5f);  // This function is not intended to be running on Mobile,
                                                        // therefore epsilon is smaller than can be represented by half
        #else
            // Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough)
            float a = roughness;
            float lambdaV = NdotL * (NdotV * (1 - a) + a);
            float lambdaL = NdotV * (NdotL * (1 - a) + a);
        
        #if defined(SHADER_API_SWITCH)
            return 0.5f / (lambdaV + lambdaL + 1e-4f); // work-around against hlslcc rounding error
        #else
            return 0.5f / (lambdaV + lambdaL + 1e-5f);
        #endif
        
        #endif
        }
        
        inline float <a name ="GGXTerm">GGXTerm</a> (float NdotH, float roughness)
        {
            float a2 = roughness * roughness;
            float d = (NdotH * a2 - NdotH) * NdotH + 1.0f; // 2 mad
            return UNITY_INV_PI * a2 / (d * d + 1e-7f); // This function is not intended to be running on Mobile,
                                                    // therefore epsilon is smaller than what can be represented by half
        }
        
        inline half <a name ="PerceptualRoughnessToSpecPower">PerceptualRoughnessToSpecPower</a> (half perceptualRoughness)
        {
            half m = PerceptualRoughnessToRoughness(perceptualRoughness);   // m is the true academic roughness.
            half sq = max(1e-4f, m*m);
            half n = (2.0 / sq) - 2.0;                          // https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
            n = max(n, 1e-4f);                                  // prevent possible cases of pow(0,0), which could happen when roughness is 1.0 and NdotH is zero
            return n;
        }
        
        // BlinnPhong normalized as normal distribution function (NDF)
        // for use in micro-facet model: spec=D*G*F
        // eq. 19 in https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
        inline half <a name ="NDFBlinnPhongNormalizedTerm">NDFBlinnPhongNormalizedTerm</a> (half NdotH, half n)
        {
            // norm = (n+2)/(2*pi)
            half normTerm = (n + 2.0) * (0.5/UNITY_PI);
        
            half specTerm = pow (NdotH, n);
            return specTerm * normTerm;
        }
        
        //-------------------------------------------------------------------------------------
        /*
        // https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
        
        const float k0 = 0.00098, k1 = 0.9921;
        // pass this as a constant for optimization
        const float fUserMaxSPow = 100000; // sqrt(12M)
        const float g_fMaxT = ( exp2(-10.0/fUserMaxSPow) - k0)/k1;
        float GetSpecPowToMip(float fSpecPow, int nMips)
        {
           // Default curve - Inverse of TB2 curve with adjusted constants
           float fSmulMaxT = ( exp2(-10.0/sqrt( fSpecPow )) - k0)/k1;
           return float(nMips-1)*(1.0 - clamp( fSmulMaxT/g_fMaxT, 0.0, 1.0 ));
        }
        
            //float specPower = PerceptualRoughnessToSpecPower(perceptualRoughness);
            //float mip = GetSpecPowToMip (specPower, 7);
        */
        
        inline float3 <a name ="Unity_SafeNormalize">Unity_SafeNormalize</a>(float3 inVec)
        {
            float dp3 = max(0.001f, dot(inVec, inVec));
            return inVec * rsqrt(dp3);
        }
        
        //-------------------------------------------------------------------------------------
        
        // Note: BRDF entry points use smoothness and oneMinusReflectivity for optimization
        // purposes, mostly for DX9 SM2.0 level. Most of the math is being done on these (1-x) values, and that saves
        // a few precious ALU slots.
        
        
        // Main Physically Based BRDF
        // Derived from Disney work and based on Torrance-Sparrow micro-facet model
        //
        //   BRDF = kD / pi + kS * (D * V * F) / 4
        //   I = BRDF * NdotL
        //
        // * NDF (depending on UNITY_BRDF_GGX):
        //  a) Normalized BlinnPhong
        //  b) GGX
        // * Smith for Visiblity term
        // * Schlick approximation for Fresnel
        half4 <a name ="BRDF1_Unity_PBS">BRDF1_Unity_PBS</a> (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,
            float3 normal, float3 viewDir,
            UnityLight light, UnityIndirect gi)
        {
            float perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
            float3 halfDir = Unity_SafeNormalize (float3(light.dir) + viewDir);
        
        // NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
        // In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
        // but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
        // Following define allow to control this. Set it to 0 if ALU is critical on your platform.
        // This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
        // Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
        #define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0
        
        #if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
            // The amount we shift the normal toward the view vector is defined by the dot product.
            half shiftAmount = dot(normal, viewDir);
            normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
            // A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
            //normal = normalize(normal);
        
            float nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
        #else
            half nv = abs(dot(normal, viewDir));    // This abs allow to limit artifact
        #endif
        
            float nl = saturate(dot(normal, light.dir));
            float nh = saturate(dot(normal, halfDir));
        
            half lv = saturate(dot(light.dir, viewDir));
            half lh = saturate(dot(light.dir, halfDir));
        
            // Diffuse term
            half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;
        
            // Specular term
            // HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
            // BUT 1) that will make shader look significantly darker than Legacy ones
            // and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
            float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
        #if UNITY_BRDF_GGX
            // GGX with roughtness to 0 would mean no specular at all, using max(roughness, 0.002) here to match HDrenderloop roughtness remapping.
            roughness = max(roughness, 0.002);
            float V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
            float D = GGXTerm (nh, roughness);
        #else
            // Legacy
            half V = SmithBeckmannVisibilityTerm (nl, nv, roughness);
            half D = NDFBlinnPhongNormalizedTerm (nh, PerceptualRoughnessToSpecPower(perceptualRoughness));
        #endif
        
            float specularTerm = V*D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later
        
        #   ifdef UNITY_COLORSPACE_GAMMA
                specularTerm = sqrt(max(1e-4h, specularTerm));
        #   endif
        
            // specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
            specularTerm = max(0, specularTerm * nl);
        #if defined(_SPECULARHIGHLIGHTS_OFF)
            specularTerm = 0.0;
        #endif
        
            // surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
            half surfaceReduction;
        #   ifdef UNITY_COLORSPACE_GAMMA
                surfaceReduction = 1.0-0.28*roughness*perceptualRoughness;      // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
        #   else
                surfaceReduction = 1.0 / (roughness*roughness + 1.0);           // fade \in [0.5;1]
        #   endif
        
            // To provide true Lambert lighting, we need to be able to kill specular completely.
            specularTerm *= any(specColor) ? 1.0 : 0.0;
        
            half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
            half3 color =   diffColor * (gi.diffuse + light.color * diffuseTerm)
                            + specularTerm * light.color * FresnelTerm (specColor, lh)
                            + surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);
        
            return half4(color, 1);
        }
        
        // Based on Minimalist CookTorrance BRDF
        // Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255
        //
        // * NDF (depending on UNITY_BRDF_GGX):
        //  a) BlinnPhong
        //  b) [Modified] GGX
        // * Modified Kelemen and Szirmay-​Kalos for Visibility term
        // * Fresnel approximated with 1/LdotH
        half4 <a name ="BRDF2_Unity_PBS">BRDF2_Unity_PBS</a> (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,
            float3 normal, float3 viewDir,
            UnityLight light, UnityIndirect gi)
        {
            float3 halfDir = Unity_SafeNormalize (float3(light.dir) + viewDir);
        
            half nl = saturate(dot(normal, light.dir));
            float nh = saturate(dot(normal, halfDir));
            half nv = saturate(dot(normal, viewDir));
            float lh = saturate(dot(light.dir, halfDir));
        
            // Specular term
            half perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
            half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
        
        #if UNITY_BRDF_GGX
        
            // GGX Distribution multiplied by combined approximation of Visibility and Fresnel
            // See "Optimizing PBR for Mobile" from Siggraph 2015 moving mobile graphics course
            // https://community.arm.com/events/1155
            half a = roughness;
            float a2 = a*a;
        
            float d = nh * nh * (a2 - 1.f) + 1.00001f;
        #ifdef UNITY_COLORSPACE_GAMMA
            // Tighter approximation for Gamma only rendering mode!
            // DVF = sqrt(DVF);
            // DVF = (a * sqrt(.25)) / (max(sqrt(0.1), lh)*sqrt(roughness + .5) * d);
            float specularTerm = a / (max(0.32f, lh) * (1.5f + roughness) * d);
        #else
            float specularTerm = a2 / (max(0.1f, lh*lh) * (roughness + 0.5f) * (d * d) * 4);
        #endif
        
            // on mobiles (where half actually means something) denominator have risk of overflow
            // clamp below was added specifically to "fix" that, but dx compiler (we convert bytecode to metal/gles)
            // sees that specularTerm have only non-negative terms, so it skips max(0,..) in clamp (leaving only min(100,...))
        #if defined (SHADER_API_MOBILE)
            specularTerm = specularTerm - 1e-4f;
        #endif
        
        #else
        
            // Legacy
            half specularPower = PerceptualRoughnessToSpecPower(perceptualRoughness);
            // Modified with approximate Visibility function that takes roughness into account
            // Original ((n+1)*N.H^n) / (8*Pi * L.H^3) didn't take into account roughness
            // and produced extremely bright specular at grazing angles
        
            half invV = lh * lh * smoothness + perceptualRoughness * perceptualRoughness; // approx ModifiedKelemenVisibilityTerm(lh, perceptualRoughness);
            half invF = lh;
        
            half specularTerm = ((specularPower + 1) * pow (nh, specularPower)) / (8 * invV * invF + 1e-4h);
        
        #ifdef UNITY_COLORSPACE_GAMMA
            specularTerm = sqrt(max(1e-4f, specularTerm));
        #endif
        
        #endif
        
        #if defined (SHADER_API_MOBILE)
            specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
        #endif
        #if defined(_SPECULARHIGHLIGHTS_OFF)
            specularTerm = 0.0;
        #endif
        
            // surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(realRoughness^2+1)
        
            // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
            // 1-x^3*(0.6-0.08*x)   approximation for 1/(x^4+1)
        #ifdef UNITY_COLORSPACE_GAMMA
            half surfaceReduction = 0.28;
        #else
            half surfaceReduction = (0.6-0.08*perceptualRoughness);
        #endif
        
            surfaceReduction = 1.0 - roughness*perceptualRoughness*surfaceReduction;
        
            half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
            half3 color =   (diffColor + specularTerm * specColor) * light.color * nl
                            + gi.diffuse * diffColor
                            + surfaceReduction * gi.specular * FresnelLerpFast (specColor, grazingTerm, nv);
        
            return half4(color, 1);
        }
        
        sampler2D_float unity_NHxRoughness;
        half3 <a name ="BRDF3_Direct">BRDF3_Direct</a>(half3 diffColor, half3 specColor, half rlPow4, half smoothness)
        {
            half LUT_RANGE = 16.0; // must match range in NHxRoughness() function in GeneratedTextures.cpp
            // Lookup texture to save instructions
            half specular = tex2D(unity_NHxRoughness, half2(rlPow4, SmoothnessToPerceptualRoughness(smoothness))).r * LUT_RANGE;
        #if defined(_SPECULARHIGHLIGHTS_OFF)
            specular = 0.0;
        #endif
        
            return diffColor + specular * specColor;
        }
        
        half3 <a name ="BRDF3_Indirect">BRDF3_Indirect</a>(half3 diffColor, half3 specColor, UnityIndirect indirect, half grazingTerm, half fresnelTerm)
        {
            half3 c = indirect.diffuse * diffColor;
            c += indirect.specular * lerp (specColor, grazingTerm, fresnelTerm);
            return c;
        }
        
        // Old school, not microfacet based Modified Normalized Blinn-Phong BRDF
        // Implementation uses Lookup texture for performance
        //
        // * Normalized BlinnPhong in RDF form
        // * Implicit Visibility term
        // * No Fresnel term
        //
        // TODO: specular is too weak in Linear rendering mode
        half4 <a name ="BRDF3_Unity_PBS">BRDF3_Unity_PBS</a> (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,
            float3 normal, float3 viewDir,
            UnityLight light, UnityIndirect gi)
        {
            float3 reflDir = reflect (viewDir, normal);
        
            half nl = saturate(dot(normal, light.dir));
            half nv = saturate(dot(normal, viewDir));
        
            // Vectorize Pow4 to save instructions
            half2 rlPow4AndFresnelTerm = Pow4 (float2(dot(reflDir, light.dir), 1-nv));  // use R.L instead of N.H to save couple of instructions
            half rlPow4 = rlPow4AndFresnelTerm.x; // power exponent must match kHorizontalWarpExp in NHxRoughness() function in GeneratedTextures.cpp
            half fresnelTerm = rlPow4AndFresnelTerm.y;
        
            half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
        
            half3 color = BRDF3_Direct(diffColor, specColor, rlPow4, smoothness);
            color *= light.color * nl;
            color += BRDF3_Indirect(diffColor, specColor, gi, grazingTerm, fresnelTerm);
        
            return half4(color, 1);
        }
        
        // Include deprecated function
        #define INCLUDE_UNITY_STANDARD_BRDF_DEPRECATED
        #include "UnityDeprecated.cginc"
        #undef INCLUDE_UNITY_STANDARD_BRDF_DEPRECATED
        
        #endif // UNITY_STANDARD_BRDF_INCLUDED
        
</pre>
<script src="https://xibanya.github.io/ShaderTutorials/CGIncludes/code-prettify/loader/run_prettify.js?skin=vscode"></script>
<script src="https://xibanya.github.io/ShaderTutorials/CGIncludes/Data/link_definitions.js"></script>
</body></html>